package com.jsyxdl.listener;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.hustcad.plm.pdm.common.model.dto.search.SearchConditionDTO;
import com.hustcad.plm.pdm.common.util.CommonUtil;
import com.hustcad.plm.pdm.doc.service.TyplmDocumentService;
import com.hustcad.plm.pdm.doc.vo.DocDetails;
import com.hustcad.plm.pdm.file.model.constant.FileErrorCodeEnum;
import com.hustcad.plm.pdm.file.model.dto.BatchUploadDTO;
import com.hustcad.plm.pdm.file.model.dto.ContentUploadDTO;
import com.hustcad.plm.pdm.file.model.entity.FileDownCenterDO;
import com.hustcad.plm.pdm.file.model.entity.FileDownQueueDO;
import com.hustcad.plm.pdm.file.model.vo.DownloadDocVO;
import com.hustcad.plm.pdm.file.model.vo.DownloadOptionVO;
import com.hustcad.plm.pdm.file.service.FileDownCenterService;
import com.hustcad.plm.pdm.file.service.QueryDownloadDocService;
import com.hustcad.plm.pdm.file.service.TyplmFileHandleService;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowChgFormView;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowObject;
import com.hustcad.plm.pdm.flowbusiness.model.entity.WorkFlowObjectPackage;
import com.hustcad.plm.pdm.workflow.annotion.CustomListener;
import com.hustcad.plm.pdm.workflow.model.entity.WorkFlowContainer;
import com.hustcad.plm.pdm.workflow.model.entity.WorkFlowContainerView;
import com.hustcad.plm.pdm.workflow.service.TyplmWorkFlowContainerService;
import com.jsyxdl.utils.FileToMultipartFileAdapter;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.handler.exceptionhandler.exception.ResponseCodeEnum;
import com.ty.basic.handler.exceptionhandler.exception.TyException;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.security.util.TyCommonUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@CustomListener(
        category = "流程审批内容收集与打包"
        , description = "流程审批内容收集与打包"
)
public class PackageProcessApprovalContentListener implements ExecutionListener, TaskListener {
    private static final Logger log = LoggerFactory.getLogger(PackageProcessApprovalContentListener.class);

    @Override
    public void notify(DelegateExecution delegateExecution) {
        log.info("流程审批内容收集与打包");
        try {
            String workFlowContainerIdStr = delegateExecution.getProcessInstanceBusinessKey();
            BigInteger workFlowContainerId = new BigInteger(workFlowContainerIdStr);
            TyplmWorkFlowContainerService typlmWorkFlowContainerService = SpringUtil.getBean(TyplmWorkFlowContainerService.class);
            if(typlmWorkFlowContainerService!=null){
                WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(workFlowContainerId);
                if(workFlowContainerView instanceof WorkFlowObjectPackage){
                    WorkFlowObjectPackage workFlowObjectPackage= (WorkFlowObjectPackage) workFlowContainerView;
                    if(workFlowObjectPackage.getFlowObjectList()!=null && workFlowObjectPackage.getFlowObjectList().size()!=0){
                        CollectPack(workFlowContainerIdStr,workFlowObjectPackage.getFlowObjectList());
                    }
                }
                else if(workFlowContainerView instanceof FlowChgFormView){

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("监听PackageProcessApprovalContentListener异常：", e);
            throw e;
        }
    }

    @Override
    public void notify(DelegateTask delegateTask) {
        log.info("流程审批内容收集与打包");
        try {
            String workFlowContainerIdStr = delegateTask.getVariable("workFlowContainerId").toString();
            BigInteger workFlowContainerId = new BigInteger(workFlowContainerIdStr);
            TyplmWorkFlowContainerService typlmWorkFlowContainerService = SpringUtil.getBean(TyplmWorkFlowContainerService.class);
            if(typlmWorkFlowContainerService!=null){
                WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(workFlowContainerId);
                if(workFlowContainerView instanceof WorkFlowObjectPackage){
                    WorkFlowObjectPackage workFlowObjectPackage= (WorkFlowObjectPackage) workFlowContainerView;
                    if(workFlowObjectPackage.getFlowObjectList()!=null && workFlowObjectPackage.getFlowObjectList().size()!=0){
                        CollectPack(workFlowContainerIdStr,workFlowObjectPackage.getFlowObjectList());
                    }
                }
                else if(workFlowContainerView instanceof FlowChgFormView){

                }
            }

        } catch (Exception e) {
            log.error("监听PackageProcessApprovalContentListener异常：", e);
            throw e;
        }
    }

    public void CollectPack(String workFlowContainerId,List<FlowObject> flowObjectList){
        TyplmDocumentService typlmDocumentService=SpringUtil.getBean(TyplmDocumentService.class);
        FileDownCenterService fileDownCenterService=SpringUtil.getBean(FileDownCenterService.class);

        List<DownloadDocVO> downloadDocList=new ArrayList<>();
        for(int i=0;i<flowObjectList.size();i++){
            FlowObject flowObject=flowObjectList.get(i);
            BigInteger newBOMPartOid = flowObject.getRefObjectOid();
            String oType = flowObject.getRefObjectOtype();
            if("ty.inteplm.cad.CTyCADDoc".equals(oType)){
                DocDetails docDetails = typlmDocumentService.queryDocDetails(newBOMPartOid, oType);
                DownloadDocVO downloadDocVO=new DownloadDocVO();
                downloadDocVO.setDocName(docDetails.getName());
                downloadDocVO.setDocNumber(docDetails.getObjectNumber());
                downloadDocVO.setOid(docDetails.getOid());
                downloadDocVO.setOtype(docDetails.getOtype());
                downloadDocList.add(downloadDocVO);

                DownloadOptionVO downloadOption = new DownloadOptionVO();
                downloadOption.setCadStructRule("asstored");
                downloadOption.setIsAllFolder("0");
                downloadOption.setIsFolder("0");
                downloadOption.setIsFolderPath("0");
                downloadOption.setIsLightweight("1");
                downloadOption.setIsSign("0");
                downloadOption.setIsSource("1");
                downloadOption.setIsWater("0");
                downloadOption.setLightWeightSuffix("pdf");
                UserDO userDO = CommonUtil.getUser();
                downloadOption.setUserOid(String.valueOf(userDO.getOid()));
                downloadOption.setWaterContent("");
                downloadOption.setWaterRoute("");
                downloadOption.setWaterType("");

                SearchConditionDTO conditionDTO=new SearchConditionDTO();
                conditionDTO.setConditionGroups(new ArrayList<>());
                conditionDTO.setConditionJoint("or");
                conditionDTO.setNeedIBA(false);
                conditionDTO.setNeedThumbnailFile(false);
                conditionDTO.setSearchType(1);
                conditionDTO.setPageNum(1);
                conditionDTO.setPageSize(99999999);
                downloadOption.setConditionDTO(conditionDTO);

                downloadOption.setDownloadDocList(downloadDocList);

                DownloadOptionVO downloadOptionVO=fileDownCenterService.queryDownloadDocList(downloadOption);

                batchDownloadFileByDocList(workFlowContainerId,downloadOptionVO);
            }
        }


    }
    public void batchDownloadFileByDocList(String workFlowContainerId, DownloadOptionVO downloadOptionVO) {
        QueryDownloadDocService queryDownloadDocService=SpringUtil.getBean(QueryDownloadDocService.class);
        SnowflakeIdComponent snowflakeIdComponent =  SpringUtil.getBean(SnowflakeIdComponent.class);
        FileDownCenterService fileDownCenterService=SpringUtil.getBean(FileDownCenterService.class);
        TyplmWorkFlowContainerService typlmWorkFlowContainerService = SpringUtil.getBean(TyplmWorkFlowContainerService.class);

        WorkFlowContainer workFlowContainer = typlmWorkFlowContainerService.selectOneByOid(
                new BigInteger(workFlowContainerId));

        String addExcel2ObjectOid = workFlowContainerId;
        String addExcel2ObjectOtype = workFlowContainer.getBaseObjectOtype();


        if (!ObjectUtils.isEmpty(downloadOptionVO)) {
            UserDO userDO = CommonUtil.getUser();
            log.info(">>>downloadOptionVO" + JSON.toJSONString(downloadOptionVO));
            FileDownCenterDO fileDownCenterDO = new FileDownCenterDO();
            List<FileDownQueueDO> fileDownQueueDOList = new ArrayList();
            String isFolderPath = "0";
            if ("1".equals(downloadOptionVO.getIsFolder()) || "1".equals(
                    downloadOptionVO.getIsFolderPath())) {
                isFolderPath = "1";
            }
            queryDownloadDocService.parseFileDownInfoByDownloadOptionVO(downloadOptionVO,
                                                                        fileDownCenterDO,
                                                                        fileDownQueueDOList, userDO,
                                                                        isFolderPath);
            if (!CollUtil.isEmpty(fileDownQueueDOList)) {
                String isFlow = downloadOptionVO.getIsFlow();

                //@Value("${filedowncenter.path:/data01/pdm/filedownload}")
                //private String downloadPath
                String downloadPath = SpringUtil.getProperty("filedowncenter.path");
                if (!org.springframework.util.StringUtils.hasText(downloadPath)) {
                    downloadPath = "/data01/pdm/filedownload";
                }
                log.info(">>>downloadPath" + downloadPath);
                boolean isSpace = checkHasSpace(downloadPath, downloadOptionVO.getTotalFileSize());
                log.info(">>>isSpace:" + isSpace);
                String isAsync = String.valueOf(downloadOptionVO.getIsAsync());
                fileDownCenterDO.setLightweightsuffix(downloadOptionVO.getLightWeightSuffix());
                if ("0".equals(isAsync) && !"1".equals(isFlow)) {
                    log.info("同步下载 >>>>>synchronizeDown start");
                    if (!isSpace) {
                        throw FileErrorCodeEnum.OUT_OF_SPEACE.getException(new Object[]{downloadPath});
                    }

                    //以下代码参考后面这个方法编写
                    //                                fileDownCenterService.synchronizeDown(response, fileDownCenterDO, fileDownQueueDOList);
                    fileDownCenterDO.setOid(snowflakeIdComponent.getInstance().nextId());
                    Map<String, String> pathAndLog = this.getPathAndLog(fileDownCenterDO);
                    String folderTempName = (String) pathAndLog.get("folderTempName");
                    String zipFolderName = (String) pathAndLog.get("zipFolderName");
                    String zipPath = zipFolderName + fileDownCenterDO.getFilename();
                    fileDownCenterService.getDownFile(zipPath, fileDownCenterDO, fileDownQueueDOList,
                                                      folderTempName, (Boolean) null);
                    File zipFile = new File(zipPath);

                    //把压缩文件添加到流程中
                    MultipartFile multipartFile = new FileToMultipartFileAdapter(zipFile, "application/zip");
                    addFile2WorkFlowContainer(Collections.singletonList(multipartFile), addExcel2ObjectOid, addExcel2ObjectOtype);
                    FileUtils.deleteQuietly(zipFile.getParentFile());
                }
            }
        }

    }
    /**
     * 检查指定路径的磁盘空间
     * @param downloadPath
     * @param docSize
     * @return
     */
    public static boolean checkHasSpace(String downloadPath, String docSize) {
        log.info(">>>checkHasSpace start");
        boolean result = true;
        File diskPartition = new File(downloadPath);
        log.info(">>>downloadPath" + downloadPath);
        File writename = new File(downloadPath);
        if (!writename.exists()) {
            log.info(">>>create folder" + downloadPath);
            writename.mkdirs();
        }

        long freePartitionSpace = diskPartition.getFreeSpace();
        log.info(">>freePartitionSpace:" + freePartitionSpace);
        if (StringUtils.isNoneBlank(new CharSequence[]{docSize}) && StringUtils.isNumeric(docSize)) {
            long size = Long.parseLong(docSize);
            log.info(">>>size" + size);
            if (size > freePartitionSpace * 2L) {
                result = false;
            }
        }

        return result;
    }
    /**
     * 获取临时文件夹和打包zip包文件夹
     * @param downloadTask
     * @return
     */
    private Map<String, String> getPathAndLog(FileDownCenterDO downloadTask) {
        String downloadPath = SpringUtil.getProperty("filedowncenter.path");
        if (!org.springframework.util.StringUtils.hasText(downloadPath)) {
            downloadPath = "/data01/pdm/filedownload";
        }
        String folderTempName = downloadPath + File.separator + downloadTask.getOid()
                .toString() + File.separator + "temp";
        log.info("下载中心定时任务打包临时目录：{}", folderTempName);
        String zipFolderName = downloadPath + File.separator + downloadTask.getOid().toString() + File.separator;
        log.info("下载中心定时任务打包zip包目录：{}", zipFolderName);
        Map<String, String> result = new HashMap(2);
        result.put("folderTempName", folderTempName);
        result.put("zipFolderName", zipFolderName);
        return result;
    }
    /**
     * 往流程中添加文件
     *
     * @param fileList 文件列表
     * @param workFlowContainerId 流程id，对于变更是baseOid
     * @param workFlowBaseOtype 流程类型
     */
    public void addFile2WorkFlowContainer(List<MultipartFile> fileList, String workFlowContainerId, String workFlowBaseOtype) {
        TyplmFileHandleService typlmFileHandleService = (TyplmFileHandleService) SpringUtil.getBean(
                TyplmFileHandleService.class);
        workFlowBaseOtype="com.ty.entity.workFlow.WorkFlowContainer";

        BatchUploadDTO batchUploadDTO = new BatchUploadDTO();
        batchUploadDTO.setOid(workFlowContainerId);
        batchUploadDTO.setOtype(workFlowBaseOtype);
        TyCommonUtils.requireNonNull(fileList, "fileList");
        TyCommonUtils.requireNonNull(batchUploadDTO, "batchUploadDTO");
        TyCommonUtils.requireNonNull(batchUploadDTO.getOid(), "oid");
        TyCommonUtils.requireNonNull(batchUploadDTO.getOtype(), "otype");
        batchUploadDTO.setFileList(fileList);
        String parentFileId = batchUploadDTO.getParentFileId();
        if (StringUtils.isNotBlank(parentFileId)) {
            String roleKey = batchUploadDTO.getRoleKey();
            if (StringUtils.isBlank(roleKey)) {
                TyException.throwSingleTyExceptionVarargs(ResponseCodeEnum.ACC_PARAMETER_IS_NULL,
                                                          new String[]{"roleKey"});
            }
        }
        List<ContentUploadDTO> contentUploadDTOS = typlmFileHandleService.batchUploadFile(batchUploadDTO);
    }
}
